package kevin.framework.basic.common.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.web.context.WebApplicationContext;
import org.w3c.dom.Document;

import kevin.framework.basic.common.ui.DataGrid;
import kevin.framework.basic.common.ui.DataGridHelper;
import kevin.framework.basic.common.user.IUserOperatorRecorder;
import kevin.framework.basic.domain.Func;
import kevin.framework.basic.domain.Menu;
import kevin.framework.basic.domain.User;
import kevin.framework.basic.service.IFuncService;
import kevin.framework.basic.service.IMenuService;
import kevin.framework.basic.service.IUserService;

/**
 * @ClassName: SpringContextUtil
 * @Description: 存放spring上下文环境,当spring环境创建完成后，开始初始化多数据源，多数据源初始化完成后，
 *               触发IOnDataSourceCreated,如果不需要初始化多数据源，则直接触发IOnDataSourceCreated
 * @author kevin.huang
 * @date 2015-12-10 下午5:30:49
 */
public class SpringContextUtil implements ApplicationContextAware, IOnDataSourceCreated {

	private static ISpringContextListener springContextListener = null;

	public final static Logger logger = LoggerFactory.getLogger(SpringContextUtil.class);

	public static void setSpringContextListener(ISpringContextListener springContextListener) {
		SpringContextUtil.springContextListener = springContextListener;
	}

	private static WebApplicationContext webContext = null; // Spring-mvc应用上下文环境

	private static ApplicationContext applicationContext; // Spring应用上下文环境

	public static boolean needToSetWebContext = true;

	public static WebApplicationContext getWebContext() {
		return webContext;
	}

	public static void setWebContext(WebApplicationContext webContext) {
		SpringContextUtil.webContext = webContext;
		needToSetWebContext = false;
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}

	public static void onContextDestroyed(final IBeforeContextDestroyed beforeDestory) {
		if (springContextListener != null) {
			springContextListener.onBeforeEvnDestory();
		}
		Object logBean = getBean("logRecorder");
		if (logBean != null) {
			IUserOperatorRecorder recoder = (IUserOperatorRecorder) logBean;
			recoder.shutdownLogThreadPool(new IOnShutdownLogThreadPool() {
				@Override
				public void hasShutdown() {
					beforeDestory.destroyed();
				}
			});
		} else {
			beforeDestory.destroyed();
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		/** 初始化数据库 ****/
		if (logger.isDebugEnabled()) {
			logger.debug("the Spring ApplicationContext loaded ok,going to initDataSource.......");
		}
		SpringContextUtil.applicationContext = arg0;
		List<DataSourceInfo> dbList = null;
		if (springContextListener != null) {
			dbList = springContextListener.setDataSourceList();
		}			
		if (dbList != null ) {
			kevin.framework.basic.common.utils.DynamicDaoSupport.initDataSource(dbList, arg0, this);
		}
		// 读取所有的datagrid配置的url/按钮数据形成func功能表的数据
		if (SysConfigParams.isDevModel) {
			try {
				IMenuService menuService = (IMenuService) getBean("menuService");
				IFuncService funcService = (IFuncService) getBean("funcService");
				Map<String, Object> param = new HashMap<String, Object>();
				param.put("controller", 1);
				Map<String, Menu> menuMap = menuService.selectMap(param, "controller");

				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
				DocumentBuilder builder = factory.newDocumentBuilder();
				PathMatchingResourcePatternResolver resoler = new PathMatchingResourcePatternResolver();
				String datagridCfg = "classpath*:/configHome/datagrid/**/*-datagrid.xml";
				System.out.println("Start <<<<< 读取datagrid配置，将配置的功能写入func表  >>>>>>>");
				Resource[] dataGridResource = resoler.getResources(datagridCfg);
				for (Resource r : dataGridResource) {
					InputStream xmlinput = r.getInputStream();
					Document docgrid = builder.parse(xmlinput);
					DataGrid grid = DataGridHelper.readGridFromXml(docgrid, null);
					String url = grid.getUrl().replace("/list", "");
					Menu menu = menuMap.get(url);
					if (menu != null) {
						Map<String, String> cmdArr = grid.getAllCmdDesp();
						Set<Entry<String, String>> entrySet = cmdArr.entrySet();
						List<Func> listFunc = new ArrayList<Func>();
						for (Entry<String, String> es : entrySet) {
							Func f = new Func();
							f.setCreateTime(new Date());
							String cmd = es.getValue();
							if ("delete".equals(cmd)) {
								f.setIsLog("1");
							} else {
								f.setIsLog("0");
							}
							f.setFuncDesc(es.getKey());
							f.setFuncCode(cmd);
							f.setMenuId(menu.getId());
							listFunc.add(f);
						}
						Func queryf = new Func();
						queryf.setCreateTime(new Date());
						queryf.setIsLog("0");
						queryf.setFuncDesc("查询");
						queryf.setFuncCode("list");
						queryf.setMenuId(menu.getId());
						listFunc.add(queryf);

						funcService.insertList(listFunc);
					}
				}
				System.out.println("End <<<<< 配置的功能写入func表 >>>>>> ");
				IUserService userService = (IUserService) getBean("userService");
				User superAdmin = userService.get("0");
				if (superAdmin == null) {
					System.out.println("End <<<<< 初始化系统超级用户 >>>>>> ");
					String pwd = DigestUtils.md5Hex(SysConfigParams.getConfig("adminPwd"));
					String name = SysConfigParams.getConfig("superAdmin");
					String adminName = SysConfigParams.getConfig("adminName");
					userService.insertSuperAdmin(name, adminName, pwd);
				}
			} catch (Exception ex) {

			}
		}
		if (springContextListener != null) {
			try {
				springContextListener.onEnvFinished();
			} catch (Exception ex) {
				logger.error("onSpringContextLoaded onEnvFinished call:{}", ex);
			}
		}
	}

	/**
	 * 获取对象
	 * 
	 * @param name
	 * @return Object
	 * @throws BeansException
	 */
	public static Object getBean(String name) throws BeansException {
		Object obj = null;
		try {
			if (webContext != null) {
				obj = webContext.getBean(name);
			}else {
				obj = applicationContext.getBean(name);
			}
		} catch (Exception ex) {
			logger.warn("the Spring ApplicationContext Cannot Fined the bean [" + name + "]");
		}
		return obj;
	}

	@Override
	public void onCreated(List<DataSourceInfo> failList) {
		if (failList.size() > 0) {
			StringBuffer buffer = new StringBuffer();
			buffer.append("Some DataSource init fail :");
			for (DataSourceInfo info : failList) {
				buffer.append(info.toString() +"  ");
			}
			logger.warn(buffer.toString());
		}
		if (springContextListener != null) {
			try {
				springContextListener.onDataSourceCreated(failList);
			} catch (Exception ex) {
				logger.error("onSpringContextLoaded onEnvFinished call:{}", ex);
			}
		}
	}

}
